package com.doeis.minaserver.nio;

import io.netty.util.concurrent.DefaultThreadFactory;
import io.netty.util.concurrent.ThreadPerTaskExecutor;
import io.netty.util.internal.SystemPropertyUtil;

import java.util.concurrent.Executor;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;

/****
 * 参照 NioEventLoopGroup
 * ***/
public class NioServiceEventLoopGroup {

	private final AtomicInteger childIndex = new AtomicInteger();
	private final NioServiceEventLoop[] children;

	private static final int DEFAULT_EVENT_LOOP_THREADS;

	static {
		DEFAULT_EVENT_LOOP_THREADS = Math.max(1, SystemPropertyUtil.getInt(
				"io.netty.eventLoopThreads", Runtime.getRuntime()
						.availableProcessors() * 2));
	}

	public NioServiceEventLoopGroup() {
		this(0);
	}

	public NioServiceEventLoopGroup(int nThreads) {
		this(nThreads, (Executor) null);
	}

	protected NioServiceEventLoopGroup(int nThreads, Executor executor) {
		nThreads = nThreads == 0 ? DEFAULT_EVENT_LOOP_THREADS : nThreads;

		if (nThreads <= 0) {
			throw new IllegalArgumentException(String.format(
					"nThreads: %d (expected: > 0)", nThreads));
		}

		if (executor == null) {
			executor = new ThreadPerTaskExecutor(newDefaultThreadFactory());
		}

		children = new NioServiceEventLoop[nThreads];

		for (int i = 0; i < nThreads; i++) {
			boolean success = false;
			try {
				children[i] = new NioServiceEventLoop(this, executor);
				success = true;
			} catch (Exception e) {
				// TODO: Think about if this is a good exception type
				throw new IllegalStateException(
						"failed to create a child event loop", e);
			} finally {
				if (!success) {
					for (int j = 0; j < i; j++) {
						children[j].shutdownGracefully();
					}
				}
			}
		}
	}

	public void shutdownGracefully() {
		for (NioServiceEventLoop l : children) {
			l.shutdownGracefully();
		}
	}

	protected NioServiceEventLoopGroup(int nThreads, ThreadFactory threadFactory) {
		this(nThreads, threadFactory == null ? null
				: new ThreadPerTaskExecutor(threadFactory));
	}

	protected ThreadFactory newDefaultThreadFactory() {
		return new DefaultThreadFactory(getClass());
	}

	public NioServiceEventLoop next() {
		return children[Math
				.abs(childIndex.getAndIncrement() % children.length)];
	}

}
